﻿using DevExpress.XtraEditors;
using HalconDotNet;
using ImageDefine;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ImageToolLine
{
    public class ImageActionerLine
    {
        public ImageToolLine imageTool;

        public ImageActionerLine()
        {
            imageTool = new ImageToolLine();
        }
        public ImageActionerLine(ImageToolLine toolBase)
        {
            imageTool = toolBase;

        }

        public bool Run(HalconDotNet.HImage imageInput, SmartDisplayControl.SmartDisplayControl disPlayControl)
        {
            bool bResult = false;
            GeneralLib.HiPerfTimer timer = new GeneralLib.HiPerfTimer();
            timer.Start();

            try
            {

                if (imageTool.strTraceName == "")
                {
                    RunToool(imageInput, disPlayControl);

                }
                else
                {
                    try
                    {
                        ImageToolBase toolTrace = imageTool.imageTask.dicTools[imageTool.strTraceName];
                        
                        imageTool.ImageToolResults = new List<ImageToolResult>();

                        if (toolTrace.ImageToolResults.Count > 0)
                        {
                            for (int i = 0; i < toolTrace.ImageToolResults.Count; i++)
                            {
                                RunToool(imageInput, disPlayControl, i);
                            }
                            ImageResultLine imageResultLine = imageTool.ImageToolResults[0] as ImageResultLine;
                            imageTool.ResultX = imageResultLine.ResultX;
                            imageTool.ResultY = imageResultLine.ResultY;
                            imageTool.dResultRow1 = imageResultLine.LineStartY;
                            imageTool.dResultCol1 = imageResultLine.LineStartX;
                            imageTool.dResultRow2 = imageResultLine.LineEndY;
                            imageTool.dResultCol2 = imageResultLine.LineEndY;
                            imageTool.bResultOK = imageResultLine.Result;
                        }
                        else
                        {
                            imageTool.ResultX = 0.0;
                            imageTool.ResultY = 0.0;
                            imageTool.dResultRow1 = 0.0;
                            imageTool.dResultCol1 = 0.0;
                            imageTool.dResultRow2 = 0.0;
                            imageTool.dResultCol2 = 0.0;
                            imageTool.bResultOK = false;
                        }
                    }
                    catch
                    {
                        
                    }
                }
            }
            catch//(Exception ex)
            {
                bResult = false;
                imageTool.bResultOK = false;
            }

            imageTool.dTimeUsed = timer.Duration;
            return bResult;
        }

        public bool RunToool(HImage image, SmartDisplayControl.SmartDisplayControl disWnd)
        {
           
            imageTool.ResultX = 0.0;
            imageTool.ResultY = 0.0;
            imageTool.ResultA = 0.0;
            imageTool.ResultOK = false;
            imageTool.dResultScore = 0.0;
            imageTool.ImageToolResults = new List<ImageToolResult>();
            ImageResultLine imageResultLine = new ImageResultLine();
            if (image == null || disWnd == null)
            {
                return false;
            }
            #region regtionSetting
            HRegion regionR = new HRegion();
            HRegion regionT;
            double AngleOfTrace = 0.0;
            regionR.GenRectangle2(imageTool.Setting.RowCenter, imageTool.Setting.ColumnCenter, imageTool.Setting.Phi, imageTool.Setting.Length1, imageTool.Setting.Length2);
            if (imageTool.Setting.regionIgnore != null)
                regionR = regionR.Difference(imageTool.Setting.regionIgnore);
            if (imageTool.strTraceName == "")
            {
                regionT = regionR;
                AngleOfTrace = 0.0;
            }
            else
            {
                try
                {
                    //ImageDefine.ImageToolBase toolTrace = ImageTask.ImageTaskManager.taskCenter.dicTasks[strTaskName].dicTools[actionerSettingSelf.strTraceName];

                    ImageDefine.ImageToolBase toolTrace;

                    toolTrace = imageTool.imageTask.dicTools[imageTool.strTraceName];

                    if (toolTrace is ImageDefine.IAffine)
                    {
                        ImageDefine.IAffine regionAffine = (ImageDefine.IAffine)toolTrace;
                        regionT = regionAffine.TransRegion(regionR);
                        AngleOfTrace = toolTrace.dResultA;
                    }
                    else
                    {
                        regionT = regionR;
                        AngleOfTrace = 0.0;
                    }
                }
                catch
                {
                    regionT = regionR;
                    AngleOfTrace = 0.0;
                }
            }
            HImage hImageReduce = image.ReduceDomain(regionT);
            #endregion


            #region 运行过程
            double dRowTran, dColTran, dPhiTran, dLenght1Tran, dLenght2Tran;
            regionT.SmallestRectangle2(out dRowTran, out dColTran, out dPhiTran, out dLenght1Tran, out dLenght2Tran);
            dPhiTran = imageTool.Setting.Phi + AngleToHu(AngleOfTrace);

            HHomMat2D hom2dIDentity = new HHomMat2D();
            HHomMat2D homMat2DRotate = hom2dIDentity.HomMat2dRotate(-dPhiTran, 0, 0);
            HHomMat2D homMat2DTranslate = homMat2DRotate.HomMat2dTranslate(dColTran, dRowTran);
            HTuple dColumn1, dRow1, dColumn2, dRow2;
            HOperatorSet.AffineTransPoint2d(homMat2DTranslate, new HTuple(-dLenght1Tran), new HTuple(0.0), out dColumn1, out dRow1);
            HOperatorSet.AffineTransPoint2d(homMat2DTranslate, new HTuple(dLenght1Tran), new HTuple(0.0), out dColumn2, out dRow2);


            //Create
            HMetrologyModel metrologyObject = new HMetrologyModel();
            metrologyObject.CreateMetrologyModel();
            int iWidth, iHeight;
            hImageReduce.GetImageSize(out iWidth, out iHeight);
            metrologyObject.SetMetrologyModelImageSize(iWidth, iHeight);
            HTuple iToolIndex = metrologyObject.AddMetrologyObjectLineMeasure(dRow1, dColumn1, dRow2, dColumn2, new HTuple(imageTool.Setting.Length2),
                new HTuple(imageTool.Setting.MeasureWidth), new HTuple(imageTool.Setting.Sigma), new HTuple(imageTool.Setting.Threshold), new HTuple(), new HTuple());
            if (imageTool.Setting.MeasureDir == LineMeasureDir.BlackToWhite)
            {
                metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("measure_transition"), new HTuple("positive"));
            }
            else
            {
                metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("measure_transition"), new HTuple("negative"));
            }
            metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("num_measures"), new HTuple(imageTool.Setting.MeasureNums));

            metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("measure_select"), new HTuple(imageTool.Setting.MeasureSelect.ToString()));
            metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("min_score"), new HTuple(imageTool.Setting.MinScore));
            metrologyObject.ApplyMetrologyModel(hImageReduce);

            #endregion

            #region 结果赋值
            HTuple hResult = metrologyObject.GetMetrologyObjectResult(iToolIndex, new HTuple("all"), new HTuple("result_type"), new HTuple("all_param"));

            HXLDCont countResult = metrologyObject.GetMetrologyObjectResultContour(new HTuple("all"), new HTuple("all"), new HTuple(1.5));
            HTuple hMeasureRows, hMeasureCols;
            HXLDCont countMeasure = metrologyObject.GetMetrologyObjectMeasures(new HTuple("all"), new HTuple("all"), out hMeasureRows, out hMeasureCols);
            HXLDCont countCross = new HXLDCont();
            countCross.GenCrossContourXld(hMeasureRows, hMeasureCols, new HTuple(6), new HTuple(0));

            if (imageTool.Setting.ShowMeasureWnd)
                disWnd.DispObj(countMeasure, "gray");
            if (imageTool.Setting.ShowMeasurePt)
                disWnd.DispObj(countCross, "cyan");
           
            

           
            if (hResult.Length > 0)
            {
                imageTool.ResultX = (hResult[1] + hResult[3]) / 2.0;
                imageTool.ResultY = (hResult[0] + hResult[2]) / 2.0;
                imageTool.dResultRow1 = hResult[0];
                imageTool.dResultCol1 = hResult[1];
                imageTool.dResultRow2 = hResult[2];
                imageTool.dResultCol2 = hResult[3];



                if (imageTool.Setting.ShowLine)
                {
                    disWnd.DisplayFullLine(imageTool.dResultRow1, imageTool.dResultCol1,
                    imageTool.dResultRow2, imageTool.dResultCol2, "green");
                   
                }
                if (imageTool.Setting.ShowMeasureResultLine)
                {
                    disWnd.DispArrow(imageTool.dResultRow1, imageTool.dResultCol1,
                   imageTool.dResultRow2, imageTool.dResultCol2, "blue");
 
                }


                //dScore = 0.0;
                //dAngle = 0.0;
                if (Math.Abs((hResult[3].D - hResult[1].D)) < 0.000001)
                {
                    if ((hResult[0].D - hResult[2].D) > 0)
                        imageTool.dResultA = 90.0;
                    else
                        imageTool.dResultA = 270.0;

                }
                else
                {
                    imageTool.dResultA = Math.Atan2((hResult[0].D - hResult[2].D), (hResult[3].D - hResult[1].D));
                    imageTool.dResultA = HuToAngle(imageTool.dResultA);
                }
                //让角度变成+/-180度
                double dAngleTemp = imageTool.dResultA;
                int iAngleTemp = (int)(dAngleTemp * 1000.0);
                iAngleTemp = iAngleTemp % 360000;
                dAngleTemp = (double)iAngleTemp / 1000.0;
                if (dAngleTemp > 180)
                {
                    imageTool.dResultA = dAngleTemp - 360.0;
                }
                else
                {
                    if (dAngleTemp < -180)
                    {
                        imageTool.dResultA = dAngleTemp + 360.0;
                    }
                    else
                    {
                        imageTool.dResultA = dAngleTemp;
                    }
                }
                imageTool.bResultOK = true;

                imageResultLine.ResultX = imageTool.ResultX;
                imageResultLine.ResultY = imageTool.ResultY;
                imageResultLine.ResultA = imageTool.ResultA;
                imageResultLine.ResultScore = imageTool.dResultScore;
                imageResultLine.LineStartX = imageTool.dResultCol1;
                imageResultLine.LineStartY = imageTool.dResultRow1;
                imageResultLine.LineEndX = imageTool.dResultCol2;
                imageResultLine.LineEndY = imageTool.dResultRow2;

                imageTool.ImageToolResults.Add(imageResultLine);
            }
            else
            {
                imageTool.dResultRow1 = 0.0;
                imageTool.dResultCol1 = 0.0;
                imageTool.dResultRow2 = 0.0;
                imageTool.dResultCol2 = 0.0;
                imageTool.ResultX = 0.0;
                imageTool.ResultY = 0.0;
                imageTool.ResultA = 0.0;
                imageTool.ResultOK = false;
                imageTool.dResultScore = 0.0;
                imageResultLine.ResultX = imageTool.ResultX;
                imageResultLine.ResultY = imageTool.ResultY;
                imageResultLine.ResultA = imageTool.ResultA;
                imageResultLine.ResultScore = imageTool.dResultScore;
                imageResultLine.LineStartX = imageTool.dResultCol1;
                imageResultLine.LineStartY = imageTool.dResultCol2;
                imageResultLine.LineEndX = imageTool.dResultRow1;
                imageResultLine.LineEndY = imageTool.dResultRow2;
                imageTool.ImageToolResults.Add(imageResultLine);
                return false;
            }
            #endregion
            return true;
       
        }
        public bool RunToool(HImage image, SmartDisplayControl.SmartDisplayControl disWnd, int iIndex)
        {
            
            imageTool.ResultX = 0.0;
            imageTool.ResultY = 0.0;
            imageTool.ResultA = 0.0;
            imageTool.ResultOK = false;
            imageTool.dResultScore = 0.0;
            ImageResultLine imageResultLine = new ImageResultLine();
            if (image == null || disWnd == null)
            {
                return false;
            }
            #region regtionSetting
            HRegion regionR = new HRegion();
            HRegion regionT;
            double AngleOfTrace = 0.0;
            regionR.GenRectangle2(imageTool.Setting.RowCenter, imageTool.Setting.ColumnCenter, imageTool.Setting.Phi, imageTool.Setting.Length1, imageTool.Setting.Length2);
            if (imageTool.Setting.regionIgnore != null)
                regionR = regionR.Difference(imageTool.Setting.regionIgnore);
            if (imageTool.strTraceName == "")
            {
                regionT = regionR;
                AngleOfTrace = 0.0;
            }
            else
            {
                try
                {
                    //ImageDefine.ImageToolBase toolTrace = ImageTask.ImageTaskManager.taskCenter.dicTasks[strTaskName].dicTools[actionerSettingSelf.strTraceName];

                    ImageDefine.ImageToolBase toolTrace;

                    toolTrace = imageTool.imageTask.dicTools[imageTool.strTraceName];

                    if (toolTrace is ImageDefine.IAffine)
                    {
                        ImageDefine.IAffine regionAffine = (ImageDefine.IAffine)toolTrace;
                        regionT = regionAffine.TransRegion(regionR,iIndex);
                        AngleOfTrace = toolTrace.ImageToolResults[iIndex].ResultA;
                    }
                    else
                    {
                        regionT = regionR;
                        AngleOfTrace = 0.0;
                    }
                }
                catch
                {
                    regionT = regionR;
                    AngleOfTrace = 0.0;
                }
            }
            HImage hImageReduce = image.ReduceDomain(regionT);
           // disWnd.DispObj(regionT);
            #endregion


            #region 运行过程
            double dRowTran, dColTran, dPhiTran, dLenght1Tran, dLenght2Tran;
            regionT.SmallestRectangle2(out dRowTran, out dColTran, out dPhiTran, out dLenght1Tran, out dLenght2Tran);
            dPhiTran = imageTool.Setting.Phi + AngleToHu(AngleOfTrace);

            HHomMat2D hom2dIDentity = new HHomMat2D();
            HHomMat2D homMat2DRotate = hom2dIDentity.HomMat2dRotate(-dPhiTran, 0, 0);
            HHomMat2D homMat2DTranslate = homMat2DRotate.HomMat2dTranslate(dColTran, dRowTran);
            HTuple dColumn1, dRow1, dColumn2, dRow2;
            HOperatorSet.AffineTransPoint2d(homMat2DTranslate, new HTuple(-dLenght1Tran), new HTuple(0.0), out dColumn1, out dRow1);
            HOperatorSet.AffineTransPoint2d(homMat2DTranslate, new HTuple(dLenght1Tran), new HTuple(0.0), out dColumn2, out dRow2);


            //Create
            HMetrologyModel metrologyObject = new HMetrologyModel();
            metrologyObject.CreateMetrologyModel();
            int iWidth, iHeight;
            hImageReduce.GetImageSize(out iWidth, out iHeight);
            metrologyObject.SetMetrologyModelImageSize(iWidth, iHeight);
            HTuple iToolIndex = metrologyObject.AddMetrologyObjectLineMeasure(dRow1, dColumn1, dRow2, dColumn2, new HTuple(imageTool.Setting.Length2),
                new HTuple(imageTool.Setting.MeasureWidth), new HTuple(imageTool.Setting.Sigma), new HTuple(imageTool.Setting.Threshold), new HTuple(), new HTuple());
            if (imageTool.Setting.MeasureDir == LineMeasureDir.BlackToWhite)
            {
                metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("measure_transition"), new HTuple("positive"));
            }
            else
            {
                metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("measure_transition"), new HTuple("negative"));
            }
            metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("num_measures"), new HTuple(imageTool.Setting.MeasureNums));

            metrologyObject.SetMetrologyObjectParam(iToolIndex, new HTuple("measure_select"), new HTuple(imageTool.Setting.MeasureSelect.ToString()));

            metrologyObject.ApplyMetrologyModel(hImageReduce);

            #endregion

            #region 结果赋值
            HTuple hResult = metrologyObject.GetMetrologyObjectResult(iToolIndex, new HTuple("all"), new HTuple("result_type"), new HTuple("all_param"));

            HXLDCont countResult = metrologyObject.GetMetrologyObjectResultContour(new HTuple("all"), new HTuple("all"), new HTuple(1.5));
            HTuple hMeasureRows, hMeasureCols;
            HXLDCont countMeasure = metrologyObject.GetMetrologyObjectMeasures(new HTuple("all"), new HTuple("all"), out hMeasureRows, out hMeasureCols);
            HXLDCont countCross = new HXLDCont();
            countCross.GenCrossContourXld(hMeasureRows, hMeasureCols, new HTuple(6), new HTuple(0));

            if (imageTool.Setting.ShowMeasureWnd)
                disWnd.DispObj(countMeasure, "gray");
            if (imageTool.Setting.ShowMeasurePt)
                disWnd.DispObj(countCross, "cyan");
           



            if (hResult.Length > 0)
            {
               
                imageTool.ResultX = (hResult[1] + hResult[3]) / 2.0;
                imageTool.ResultY = (hResult[0] + hResult[2]) / 2.0;
                imageTool.dResultRow1 = hResult[0];
                imageTool.dResultCol1 = hResult[1];
                imageTool.dResultRow2 = hResult[2];
                imageTool.dResultCol2 = hResult[3];

                if (imageTool.Setting.ShowLine)
                {
                    disWnd.DisplayFullLine(imageTool.dResultRow1, imageTool.dResultCol1,
                    imageTool.dResultRow2, imageTool.dResultCol2, "green");

                }


                if (imageTool.Setting.ShowMeasureResultLine)
                {
                    disWnd.DispArrow(imageTool.dResultRow1, imageTool.dResultCol1,
                       imageTool.dResultRow2, imageTool.dResultCol2, "blue");
                }
                

               

               
                if (Math.Abs((hResult[3].D - hResult[1].D)) < 0.000001)
                {
                    if ((hResult[0].D - hResult[2].D) > 0)
                        imageTool.dResultA = 90.0;
                    else
                        imageTool.dResultA = 270.0;

                }
                else
                {
                    imageTool.dResultA = Math.Atan2((hResult[0].D - hResult[2].D), (hResult[3].D - hResult[1].D));
                    imageTool.dResultA = HuToAngle(imageTool.dResultA);
                }
                //让角度变成+/-180度
                double dAngleTemp = imageTool.dResultA;
                int iAngleTemp = (int)(dAngleTemp * 1000.0);
                iAngleTemp = iAngleTemp % 360000;
                dAngleTemp = (double)iAngleTemp / 1000.0;
                if (dAngleTemp > 180)
                {
                    imageTool.dResultA = dAngleTemp - 360.0;
                }
                else
                {
                    if (dAngleTemp < -180)
                    {
                        imageTool.dResultA = dAngleTemp + 360.0;
                    }
                    else
                    {
                        imageTool.dResultA = dAngleTemp;
                    }
                }
                imageTool.bResultOK = true;

                imageResultLine.ResultX = imageTool.ResultX;
                imageResultLine.ResultY = imageTool.ResultY;
                imageResultLine.ResultA = imageTool.ResultA;
                imageResultLine.ResultScore = imageTool.dResultScore;
                imageResultLine.LineStartX = imageTool.dResultCol1;
                imageResultLine.LineStartY = imageTool.dResultRow1;
                imageResultLine.LineEndX = imageTool.dResultCol2;
                imageResultLine.LineEndY = imageTool.dResultRow2;
                imageResultLine.Result = true;

                imageTool.ImageToolResults.Add(imageResultLine);
            }
            else
            {
                imageTool.dResultRow1 = 0.0;
                imageTool.dResultCol1 = 0.0;
                imageTool.dResultRow2 = 0.0;
                imageTool.dResultCol2 = 0.0;
                imageTool.ResultX = 0.0;
                imageTool.ResultY = 0.0;
                imageTool.ResultA = 0.0;
                imageTool.ResultOK = false;
                imageTool.dResultScore = 0.0;
                imageResultLine.ResultX = imageTool.ResultX;
                imageResultLine.ResultY = imageTool.ResultY;
                imageResultLine.ResultA = imageTool.ResultA;
                imageResultLine.ResultScore = imageTool.dResultScore;
                imageResultLine.LineStartX = imageTool.dResultCol1;
                imageResultLine.LineStartY = imageTool.dResultCol2;
                imageResultLine.LineEndX = imageTool.dResultRow1;
                imageResultLine.LineEndY = imageTool.dResultRow2;
                imageResultLine.Result = false;
                imageTool.ImageToolResults.Add(imageResultLine);
                return false;
            }
            #endregion
            return true;

        }
        private double HuToAngle(double dHu)
        {
            return dHu / Math.PI * 180.0;
        }
        private double AngleToHu(double dAngle)
        {
            return dAngle / 180.0 * Math.PI;
        }
    }
}
